package drds.global_transaction.jdbc;

import drds.common.Author;
import drds.global_transaction.Authors;
import drds.global_transaction.TransactionId;
import drds.global_transaction.TransactionIdFactory;
import lombok.extern.slf4j.Slf4j;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

//import drds.global_transaction.transaction_context.TransactionId;
//import javax.transaction.xa.XAException;

@Author(name = Authors.LI_YANG)
@Slf4j
public class TransactionInfo
{
    public synchronized void addTransaction(TransactionId transactionId)
    {

        String identifier = TransactionIdFactory.globalTransactionIdWithBranchTransactionId(transactionId.getGlobalTransactionId(), transactionId.getBranchTransactionId());
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try
        {
            preparedStatement = connection.prepareStatement("insert into global_transaction(id, global_transaction, branch_transaction_id, ctime) values(?, ?, ?, ?)");
            preparedStatement.setString(1, identifier);
            preparedStatement.setString(2, transactionId.getGlobalTransactionId());
            preparedStatement.setString(3, transactionId.getBranchTransactionId());
            preparedStatement.setLong(4, System.currentTimeMillis());
            int value = preparedStatement.executeUpdate();
            if (value == 0)
            {
                throw new IllegalStateException("The operation failed and the data was not written to the database!");
            }
        } catch (SQLException ex)
        {
        } finally
        {
            try
            {
                preparedStatement.close();
            } catch (SQLException e)
            {
                e.printStackTrace();
            }
        }
    }

    public void getTransaction(TransactionId transactionId)
    {
        String x = TransactionIdFactory.globalTransactionIdWithBranchTransactionId(transactionId.getGlobalTransactionId(), transactionId.getBranchTransactionId());
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try
        {
            StringBuilder sql = new StringBuilder();
            sql.append("select id, global_transaction_id, Branch_Transaction_Id from global_transaction where id = ? and global_transaction_id = ? and Branch_Transaction_Id = ? ");
            preparedStatement = connection.prepareStatement(sql.toString());
            preparedStatement.setString(1, x);
            preparedStatement.setString(2, transactionId.getGlobalTransactionId());
            preparedStatement.setString(3, transactionId.getBranchTransactionId());
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next() == false)
            {
                throw new RuntimeException();
            }
        } catch (Exception ex)
        {
            log.warn("Error occurred while recovering local-xa-resource.", ex);
            throw new RuntimeException();
        } finally
        {


        }
    }

    public void checkTransaction(TransactionId transactionId)
    {
        String id = TransactionIdFactory.globalTransactionIdWithBranchTransactionId(transactionId.getGlobalTransactionId(), transactionId.getBranchTransactionId());

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try
        {
            connection = null;
            preparedStatement = connection.prepareStatement("select global_transaction_id, branch_transaction_id from global_transaction where id = ?");
            preparedStatement.setString(1, id);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.next() == false)
            {
                throw new RuntimeException();
            }
        } catch (SQLException ex)
        {
            throw new RuntimeException();
        } finally
        {

        }
    }

    public TransactionId[] getTransactionIds()
    {
        List<TransactionId> transactionIdList = new ArrayList<TransactionId>();

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try
        {
            connection = null;
            preparedStatement = connection.prepareStatement("select global_transaction_id, branch_transaction_id from global_transaction");
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next())
            {
                String globalTransactionId = resultSet.getString(1);
                String branchTransactionId = resultSet.getString(2);
                TransactionId transactionId = new TransactionId(globalTransactionId, branchTransactionId);
                transactionIdList.add(transactionId);
            }

        } catch (Exception ex)
        {
        } finally
        {
        }
        return (TransactionId[]) transactionIdList.toArray();
    }


    public synchronized void deleteTransactions(TransactionId[] transactionIds)
    {
        if (transactionIds == null || transactionIds.length == 0)
        {
            return;
        }

        String[] strings = new String[transactionIds.length];

        for (int i = 0; i < transactionIds.length; i++)
        {
            TransactionId transactionId = transactionIds[i];
            strings[i] = TransactionIdFactory.globalTransactionIdWithBranchTransactionId(transactionId.getGlobalTransactionId(), transactionId.getBranchTransactionId());
        }

        Connection connection = null;
        PreparedStatement preparedStatement = null;
        Boolean autoCommit = null;
        try
        {
            connection = null;
            autoCommit = connection.getAutoCommit();
            connection.setAutoCommit(false);
            preparedStatement = connection.prepareStatement("delete from global_transaction where id = ?");
            for (int i = 0; i < transactionIds.length; i++)
            {
                preparedStatement.setString(1, strings[i]);
                preparedStatement.addBatch();
            }
            preparedStatement.executeBatch();
            connection.commit();
        } catch (Exception ex)
        {
            log.error("Error occurred while forgetting resources.", ex);

            try
            {
                connection.rollback();
            } catch (Exception sqlEx)
            {
                log.error("Error occurred while rolling back local resources.", sqlEx);
            }
        } finally
        {
            if (autoCommit != null)
            {
                try
                {
                    connection.setAutoCommit(autoCommit);
                } catch (SQLException sqlEx)
                {
                    log.error("Error occurred while configuring attribute 'autoCommit'.", sqlEx);
                }
            }

        }
    }

    public synchronized void deleteTransaction(TransactionId transactionId)
    {
        if (transactionId == null)
        {
            log.warn("Error occurred while forgeting local-xa-resource: invalid globalTransactionId.");
            return;
        }
        String x = TransactionIdFactory.globalTransactionIdWithBranchTransactionId(transactionId.getGlobalTransactionId(), transactionId.getBranchTransactionId());
        Connection connection = null;
        PreparedStatement preparedStatement = null;
        try
        {
            preparedStatement = connection.prepareStatement("delete from global_transaction where id = ?");
            preparedStatement.setString(1, x);
            preparedStatement.executeUpdate();
        } catch (Exception ex)
        {

        } finally
        {

        }
    }


}
